package com.czkevin.cif.crafting.gui;

import com.czkevin.cif.CustomItemFramework;
import com.czkevin.cif.crafting.RecipeMatch;
import com.czkevin.cif.crafting.RecipeRegister;
import com.czkevin.cif.events.CIFCraftingPickupEvent;
import com.czkevin.cif.events.CIFCraftingMatchEvent;
import com.czkevin.guicontrolsapi.ItemUtils;
import com.czkevin.guicontrolsapi.controls.ButtonControl;
import com.czkevin.guicontrolsapi.controls.ProgressBarControl;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.czkevin.guicontrolsapi.Window;

public class AdvancedCraftingGUI extends Window {

    private final CraftingMatrixControl crafting = new CraftingMatrixControl(5, 5);
    private final CraftingOutputControl output = new CraftingOutputControl();

    private final ProgressBarControl progressBarControl = new ProgressBarControl(
        ProgressBarControl.VERTICAL, 5, 1.0f, 0.0f
    );

    private final ButtonControl buttonDoCraft = new ButtonControl(
        this::doCraft, "\u00a7a\u00a7lCraft", "\u00a7bClick to add progress. "
    ) {
        @Override
        public ItemStack getDisplayItem() {
            String text = "\u00a71[\u00a7a\u00a7lCraft\u00a71]";
            String[] lore;
            if(currentMatched != null) {
                if(requiredClicks > 0) {
                    final float percent = ((float) currentClicked) / ((float) requiredClicks);
                    lore = new String[] {
                        "\u00a7eCrafting... ",
                        String.format("\u00a7eProgress: \u00a7a%.2f%% \u00a77(%d/%d)", percent * 100f, currentClicked, requiredClicks)
                    };
                } else {
                    lore = new String[]{"\u00a7aCraft complete! ", "\u00a7aYou may pickup your item! "};
                }
            } else {
                lore = new String[]{"\u00a7cInvalid crafting recipe! "};
            }
            return ItemUtils.putMeta(new ItemStack(Material.LEVER), false, text, lore);
        }
    };

    private RecipeMatch currentMatched = null;

    private int currentClicked = 0;
    private int requiredClicks = 0;

    public AdvancedCraftingGUI() {
        super("\u00a7f\uf808\uef01", 8, 5);
        output.setCallback((h) -> {
            if(currentMatched == null) return false;
            if(currentClicked < requiredClicks) return false;
            final CIFCraftingPickupEvent event = new CIFCraftingPickupEvent(h, currentMatched);
            Bukkit.getPluginManager().callEvent(event);
            if(event.isCancelled()) {
                return false;
            }
            currentMatched.recipe.removeLayer(crafting.getMatrix(), currentMatched);
            crafting.applyMatrixToDisplay();
            Bukkit.getScheduler().runTaskLater(CustomItemFramework.getInstance(), () -> refreshMatch(h, crafting.getMatrix()), 1L);
            return true;
        });
        crafting.setCallback(this::refreshMatch);
        setControl(0, 0, crafting);
        setControl(6, 2, output);

        setControl(6, 3, buttonDoCraft);

        setControl(7, 0, progressBarControl);
    }

    public void refreshMatch(HumanEntity player, ItemStack[][] matrix) {
        requiredClicks = Integer.MAX_VALUE;
        currentClicked = 0;
        currentMatched = null;

        RecipeMatch tryMatched = RecipeRegister.match(matrix); // pre match
        if(tryMatched == null) {
            output.setOutput(null);
            updateDisplay();
            return;
        }

        // call event and get craft clicks
        final CIFCraftingMatchEvent event = new CIFCraftingMatchEvent(player, tryMatched, tryMatched.recipe.requiredClicks);
        Bukkit.getPluginManager().callEvent(event);
        tryMatched = event.getMatchedRecipe(); // update with event
        if(tryMatched == null || event.isCancelled()) {
            output.setOutput(null);
            return;
        }

        requiredClicks = Math.max(0, event.getRequiredClicks());
        currentMatched = tryMatched;

        doCraft(player);

        CustomItemFramework.debug(String.format("Matched <%s> at (%d, %d)", currentMatched.recipe.getName(), currentMatched.x, currentMatched.y));
        output.setOutput(currentMatched.recipe.getClonedOutput());
    }

    private void updateDisplay() {
        if(currentMatched != null) {
            if (requiredClicks == 0) {
                progressBarControl.setMaxValue(1.0f);
                progressBarControl.setValue(1.0f);
            } else {
                progressBarControl.setMaxValue(Math.max(1, requiredClicks));
                progressBarControl.setValue(Math.max(1, currentClicked));
            }
        } else {
            progressBarControl.setMaxValue(1.0f);
            progressBarControl.setValue(0.0f);
        }

        buttonDoCraft.onRender(true);
        progressBarControl.onRender(true);
    }

    private void doCraft(HumanEntity humanEntity) {
        if(currentMatched == null || currentClicked >= requiredClicks) {
            return;
        }

        currentClicked ++;
        ((Player) humanEntity).playSound(humanEntity.getEyeLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.BLOCKS, 1.0f, 1.0f);

        if(currentClicked >= requiredClicks) {
            ((Player) humanEntity).playSound(humanEntity.getEyeLocation(), Sound.ENTITY_PLAYER_LEVELUP, SoundCategory.BLOCKS, 1.0f, 1.0f);
        }

        updateDisplay();
    }

    @Override
    public void onOpenInternal(HumanEntity humanEntity) { }

    @Override
    protected boolean onCloseInternal(HumanEntity humanEntity) {
        crafting.dropAll(humanEntity.getLocation());
        return true;
    }
}
